#include "g729k.h"

void g729k_encoder_init(struct g729k_encoder *encoder) {
    init_pre_process(&encoder->pre_proc);
    init_coder_ld8k(&encoder->ld8);
}

void g729k_encoder_proc(struct g729k_encoder *encoder, const int16_t *input_pcm, uint8_t *output_bitstream) {
    int prm[PRM_SIZE]; /* Transmitted parameters */
    int i;

    for (i = 0; i < L_FRAME; i++)
        encoder->ld8.new_speech[i] = (FLOAT) input_pcm[i];

    pre_process(&encoder->pre_proc, encoder->ld8.new_speech, L_FRAME);

    coder_ld8k(&encoder->ld8, prm);

    prm2bits_ld8k_c(prm, output_bitstream);
}

void g729k_encoder_deinit(struct g729k_encoder *encoder) {

}



void g729k_decoder_init(struct g729k_decoder *decoder) {
    int i;

    init_decod_ld8k(&decoder->ld8);
    init_post_filter(&decoder->postfilter);
    init_post_process(&decoder->postprocess);

    for (i = 0; i < M; i++)
        decoder->synth_buf[i] = (F) 0.0;
    decoder->synth = decoder->synth_buf + M;

    decoder->voicing = 60;
}

void g729k_decoder_proc(struct g729k_decoder *decoder, const uint8_t *input_bitstream, int bfi, int16_t *output_pcm) {
    int i;
    int parm[PRM_SIZE+1]; /* Synthesis parameters + BFI */
    FLOAT  Az_dec[2*MP1], *ptr_Az;          /* Decoded Az for post-filter */
    int    t0_first;
    FLOAT  pst_out[L_FRAME];                /* postfilter output          */

    int sf_voic;                    /* voicing for subframe */

    parm[0] = bfi;

    bits2prm_ld8k_c(input_bitstream, parm + 1);

    /* check parity and put 1 in parm[4] if parity error */

    parm[4] = check_parity_pitch(parm[3], parm[4]);

    decod_ld8k(&decoder->ld8, parm, decoder->voicing, decoder->synth, Az_dec, &t0_first);  /* Decoder */

    /* Post-filter and decision on voicing parameter */
    decoder->voicing = 0;
    ptr_Az = Az_dec;
    for (i = 0; i < L_FRAME; i += L_SUBFR) {
        post(&decoder->postfilter, t0_first, &decoder->synth[i], ptr_Az, &pst_out[i], &sf_voic);
        if (sf_voic != 0) { decoder->voicing = sf_voic; }
        ptr_Az += MP1;
    }
    copy(decoder->synth_buf + L_FRAME, &decoder->synth_buf[0], M);

    post_process(&decoder->postprocess, pst_out, L_FRAME);

    float2int16(output_pcm, pst_out);
}

void g729k_decoder_deinit(struct g729k_decoder *decoder) {

}